/*
 * WxUtils.h
 *
 *  Created on: Sep 7, 2011
 *      Author: erudhes
 */
#ifndef WXUTILS_H_
#define WXUTILS_H_
#include <vector>
#include <wx/wx.h>

DECLARE_EVENT_TYPE(WXTASK_EVENT, 7777)

#define EVT_TASK_EVENT(fn)                                             \
	DECLARE_EVENT_TABLE_ENTRY( WXTASK_EVENT, wxID_ANY, wxID_ANY,   \
	(wxObjectEventFunction)(wxEventFunction)&fn, (wxObject*) NULL ),

class wxSocketBase;

/**
 * Class for helper methods for working with wxWidgets
 *
 * @author Rudolf Heszele heszele@gmail.com
 * @version 1.0
 * @since 2012-03-08
 */
class WxUtils
{
	public:
		/**
		 * Interface for every scheduled task class
		 *
		 * @author Rudolf Heszele heszele@gmail.com
		 * @version 1.0
		 * @since 2012-03-08
		 */
		class ITask
		{
			public:
				/**
				 * The default constructor. Does nothing
				 */
				ITask();
				/**
				 * This method will be called in the asynchron callback
				 */
				virtual void execute() = 0;
				/**
				 * The destructor must be virtual
				 */
				virtual ~ITask();
		};
		/**
		 * A special event to make the task execution asynchron
		 *
		 * This class will be used, to add this special event to wxWidgets.
		 * Events in wxWidgets handled in an async way, so we can schedule jobs easily.
		 * @author Rudolf Heszele heszele@gmail.com
		 * @version 1.0
		 * @since 2012-03-08
		 */
		class TaskEvent: public wxEvent
		{
			public:
				/**
				 * The only contructor takes the task as an argument
				 *
				 * @param task The task to be executed
				 */
				TaskEvent(ITask* task = NULL);
				TaskEvent(const TaskEvent& taskEvent);
				virtual ~TaskEvent();
				/**
				 * Has to be implemented, because wxWidgets will use it. Clones the object.
				 */
				virtual wxEvent* Clone() const;
				ITask* getTask();
				/**
				 * Sets the task to NULL
				 */
				void resetTask();

				DECLARE_DYNAMIC_CLASS(TaskEvent)

			private:
				ITask* mTask;
		};
		/**
		 * Helper class to schedule a task. Can not be instantiated
		 *
		 * @author Rudolf Heszele heszele@gmail.com
		 * @version 1.0
		 * @since 2012-03-08
		 */
		class TaskScheduler: public wxEvtHandler
		{
			public:
				/**
				 * This method will schedule a task for asynchron execution
				 *
				 * @param task The task to execute
				 */
				static void schedule(ITask* task);

			private:
				TaskScheduler();
				~TaskScheduler();
				/**
				 * This method will be called by the wxWidgets when a task can be executed
				 *
				 * By scheduling our special event, wxWidgets will send the event later to the event handlers
				 * @param event The event previously scheduled to wxWidgets. Contains the task to be executed
				 */
				void onScheduleTask(wxEvent& event);

				DECLARE_EVENT_TABLE()
		};
		/**
		 * Helper class to define colors with Red, Green, Blue values
		 *
		 * @author Rudolf Heszele heszele@gmail.com
		 * @version 1.0
		 * @since 2012-03-08
		 */
		class Color
		{
			public:
				/**
				 * The default constructor makes a black color object
				 */
				Color();
				/**
				 * With this constructor the user can create the needed color object
				 *
				 * @param red The red part of the RGB
				 * @param green The green part of the RGB
				 * @blue The blue part of the RGB
				 */
				Color(unsigned char red, unsigned char green, unsigned char blue);

				unsigned char getRed() const;
				unsigned char getGreen() const;
				unsigned char getBlue() const;
				void setRed(unsigned char red);
				void setGreen(unsigned char green);
				void setBlue(unsigned char blue);

			private:
				unsigned char mRed;
				unsigned char mGreen;
				unsigned char mBlue;
		};
		/**
		 * Enumeration for possible socket errors
		 */
		enum SocketError
		{
			NONE,
			DISCONNECTION,
			IO_ERROR,
		};

		/**
		 * Predefined color object for red color
		 */
		static const Color RED;
		/**
		 * Predefined color object for green color
		 */
		static const Color GREEN;
		/**
		 * Predefined color object for blue color
		 */
		static const Color BLUE;
		/**
		 * Predefined color object for black color
		 */
		static const Color BLACK;
		/**
		 * Predefined color object for white color
		 */
		static const Color WHITE;
		/**
		 * Predefined point object for invalid coordinates - mainly used for initialization
		 */
		static const wxPoint INVALID_POINT;
		/**
		 * Calculates the points around a point with a given radius
		 *
		 * @param point The centre. The points will be placed around the point
		 * @param radius The radius of the circle around the centre in pixels
		 * @return The list of points around the given centre
		 */
		static std::vector<wxPoint> getPointsAround(const wxPoint& point, unsigned int radius = 1);
		/**
		 * Checks for error on the given socket
		 *
		 * @param socket The socket to be checked
		 * @param size The assumed size of the last IO operation on the socket
		 * @return NONE is no error found, IO_ERROR if the assumed size is not equal to the current one, and DISCONNECTION when the connection is done.
		 */
		static SocketError getSocketError(wxSocketBase* socket, unsigned int size);
		/**
		 * Returns the IP address of the hosting machine
		 *
		 * @return THe string, containing the IP address of the hosting machine
		 */
		static wxString getLocalIpAddress();

	private:
		WxUtils();
		virtual ~WxUtils();
};

/**
 * WxUtils::TaskEvent class
 */

inline WxUtils::ITask* WxUtils::TaskEvent::getTask()
{
	return mTask;
}

inline void WxUtils::TaskEvent::resetTask()
{
	mTask = NULL;
}

/**
 * WxUtils::Color class
 */

inline unsigned char WxUtils::Color::getRed() const
{
	return mRed;
}

inline unsigned char WxUtils::Color::getGreen() const
{
	return mGreen;
}

inline unsigned char WxUtils::Color::getBlue() const
{
	return mBlue;
}

inline void WxUtils::Color::setRed(unsigned char red)
{
	mRed = red;
}

inline void WxUtils::Color::setGreen(unsigned char green)
{
	mGreen = green;
}

inline void WxUtils::Color::setBlue(unsigned char blue)
{
	mBlue = blue;
}

#endif /* WXUTILS_H_ */
